/**
 Created by:
 muhtearjan mehmood مۇختەرجان مەخمۇت (Email: yeganaaa@163.com)
 At 8/10/20 2:45 AM
 */
import {IStatefulClientInterface} from "../../src/Core/ProtocolInterface";
import {StateModuleInMemoryImplementation} from "../../src/Core/StateModuleInMemoryImplementation";

export interface WithSimpleDataType {
    sum(args: {a: number, b: number}): Promise<number>
    sayHello(name: string): Promise<string>
    reverse(value: boolean): Promise<boolean>
    counterOnState(): Promise<number>
}
export type Person = {
    name: string,
    email: string,
    birthday: number
    address: {
        country: string,
        city: string,
    },
    contacts: {name: string, value: string}[]
}
export interface WithComplexDataType {
    getSelf(person: Person): Promise<Person>
}
export interface WithBinaryDataType {
    updateImage(data: Uint8Array): Promise<Uint8Array>
}
export interface SimpleServerInterface {
    simple: WithSimpleDataType
    complex: WithComplexDataType
    binary: WithBinaryDataType
    version(): Promise<number>
    shouldBeException(): Promise<void>
}
export interface SimpleClientInterface extends IStatefulClientInterface {
    simple: WithSimpleDataType
    complex: WithComplexDataType
    binary: WithBinaryDataType
    version(): Promise<number>
    shouldBeException(): Promise<void>
}

class WithBinary implements WithBinaryDataType {
    public async updateImage(data: Uint8Array): Promise<Uint8Array> {
        return data
    }
}
const withComplex = {
    async getSelf(person: Person): Promise<Person> {
        return person
    }
}
class WithSimple implements WithSimpleDataType {
    state = {
        counter: 0
    }
    async counterOnState(): Promise<number> {
        return this.state.counter++
    }

    async reverse(value: boolean): Promise<boolean> {
        return !value
    }

    async sayHello(name: string): Promise<string> {
        return `Hello ${name}`
    }

    async sum({a, b}: { a: number; b: number }): Promise<number> {
        return a + b
    }
}

export class ServerImpl implements SimpleServerInterface {
    binary: WithBinaryDataType = new WithBinary()
    complex: WithComplexDataType = withComplex
    simple: WithSimpleDataType = new WithSimple()
    async version(): Promise<number> {
        return 1
    }
    public async shouldBeException() {
        throw new Error("ServerSide Exception")
    }
}
export class ClientImpl implements SimpleClientInterface {
    stateModule = new StateModuleInMemoryImplementation()
    public async sendErrorMessage(error: string): Promise<void> {
        console.error(error)
    }
    
    binary = new WithBinary()
    complex = withComplex
    simple = new WithSimple()
    async version(): Promise<number> {
        return 2
    }
    shouldBeException(): Promise<void> {
        throw new Error("ClientSide Exception")
    }
}